<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Amqp\Producers\CommonTaskCenterProducers;
use App\CustHub\Amqp\Producers\RobotMsgProducers;
use App\CustHub\Amqp\Producers\SendRecordProducers;
use App\CustHub\Constants\MsgTypeConstants;
use App\CustHub\Constants\SendConfigConstants;
use App\CustHub\Constants\SendRecordStatusConstants;
use App\CustHub\Dto\SendRecordProducersDto;
use App\CustHub\Helpers\TagReplacer;
use App\CustHub\Mapper\ChSmartAutoPushMapper;
use App\CustHub\Model\ChContact;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChSmartSendRecord;
use App\CustHub\Model\ChSmartTag;
use Hyperf\Amqp\Producer;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;
use function Hyperf\Coroutine\co;

/**
 * 自动推送方案服务类
 */
class ChSmartAutoPushService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChSendConfigService $sendConfigService;

    public function __construct(ChSmartAutoPushMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function getAutoPushList(array $data)
    {
        $keyword = data_get($data, 'keyword', '');
        $tagIdsStr = data_get($data, 'tag_ids', '');
        $tagIds = !empty($tagIdsStr) ? explode(',', $tagIdsStr) : [];
        $pageSize = (int)data_get($data, 'page_size', 10);

        $tagList = ChSmartTag::query()
            ->select(['id', 'name'])
            ->where('uid', $data['uid'])
            ->orderBy('sort')
            ->get()->toArray();

        $tagList = array_column($tagList, 'name', 'id');

        $paginate = $this->mapper->model::query()
            ->with(['robotList' => function ($query) {
                $query->select(['id', 'nickname','corp_id', 'avatar','corp_name','user_id','login_status']);
            }])
            ->when(!empty($keyword), function ($query) use ($keyword) {
                $query->where('title', 'like', '%' . $keyword . '%');
            })
            ->when(!empty($tagIds), function ($query) use ($tagIds) {
                foreach ($tagIds as $k => $item) {
                    $tagIds[$k] = (int)$item;
                }
                $tagIds = json_encode($tagIds);
                $query->whereRaw("JSON_CONTAINS(include_tag->'$.tag_ids', '{$tagIds}')")
                    ->orWhereRaw("JSON_CONTAINS(exclude_tag->'$.tag_ids', '{$tagIds}')");
            })
            ->where('uid', $data['uid'])
            ->orderBy('created_at', 'desc')
            ->paginate($pageSize);

        $paginate->getCollection()->transform(function ($item) use ($tagList) {
            $item->robot_count = count($item->robot_ids);
            //触发标签名称
            $includeTagNameArr = [];
            foreach ($item->include_tag['tag_ids'] as $includeTagId) {
                isset($tagList[$includeTagId]) && $includeTagNameArr[] = $tagList[$includeTagId];
            }
            $item->include_tag_name = implode(',', $includeTagNameArr);
            //排除标签名称
            $excludeTagNameArr = [];
            foreach ($item->exclude_tag['tag_ids'] as $excludeTagId) {
                isset($tagList[$excludeTagId]) && $excludeTagNameArr[] = $tagList[$excludeTagId];
            }
            $item->exclude_tag_name = implode(',', $excludeTagNameArr);

            $robotList = $item->robotList;
            $item->grouped_robot_list  = collect($robotList)
                ->groupBy('corp_id')
                ->map(function ($items, $corpId) {
                    $firstItem = $items->first();
                    return [
                        'corp_id' => $corpId,
                        'corp_name' => $firstItem['corp_name'],
                        'list' => $items->toArray()
                    ];
                })
                ->values()
                ->toArray();
            return $item;
        });

        return $this->mapper->setPaginate($paginate);
    }



    /**
     * 新增方案
     * @param array $data
     * @return mixed
     */
    public function save(array $data): mixed
    {
        $jsonField = ['robot_ids', 'include_tag', 'exclude_tag', 'content'];
        foreach ($jsonField as $item) {
            $data[$item] = json_decode($data[$item], true);
        }
        return $this->mapper->save($data);
    }


    /**
     * 更新方案
     * @param mixed $id
     * @param array $data
     * @return bool
     */
    public function update(mixed $id, array $data): bool
    {
        $info = $this->mapper->model::query()
            ->where('id', $id)
            ->where('uid', $data['uid'])
            ->first();
        if (empty($info)) {
            return false;
        }

        $jsonField = ['robot_ids', 'include_tag', 'exclude_tag', 'content'];
        foreach ($jsonField as $item) {
            $data[$item] = json_decode($data[$item], true);
        }

        return $this->mapper->update($id, $data);
    }

    /**
     * 删除方案
     * @param array $data
     * @return bool
     * @throws \Exception
     */
    public function deleteAutoPush(array $data): bool
    {
        return $this->mapper->model::query()
                ->where('id', $data['id'])
                ->where('uid', $data['uid'])
                ->delete() > 0;
    }

    /**
     * 获取满足条件的方案
     * @param mixed $uid
     * @param mixed $mainUid
     * @param array $contactIds
     * @param array $tagIds
     * @return array
     */
    public function getMeetTheConditionScheme(mixed $uid,mixed $mainUid, array $contactIds, array $tagIds): array
    {
        //查询所有启用的方案
        $list = $this->mapper->model::query()
            ->where('status', 1)
            ->where('uid', $uid)
            ->get()->toArray();

        $filterList = [];
        foreach ($list as $item) {
            //判断是否满足触发条件
            $includeTag = $item['include_tag'];
            $includeTagMatchType = $includeTag['match_type'];
            $checkIncludeTag = matchTags($includeTag['tag_ids'], $tagIds, $includeTagMatchType);
            if (!$checkIncludeTag) {
                continue;
            }

            //判断是否满足排除条件
            $excludeTag = $item['exclude_tag'];
            if ($excludeTag['switch'] == 1) {
                $excludeTagMatchType = $excludeTag['match_type'];
                $checkExcludeTag = matchTags($excludeTag['tag_ids'], $tagIds, $excludeTagMatchType);
                if ($checkExcludeTag) {
                    continue;
                }
            }
            $filterList[] = $item;
        }

        if (!empty($filterList)) {
            $contactList = ChContact::query()
                ->select(['id', 'robot_id', 'user_id','nickname','call_name'])
                ->whereIn('id', $contactIds)
                ->get();
            foreach ($filterList as $scheme){
                $recordData = [];
                foreach ($contactList as $contact){
                    if(!in_array($contact->robot_id, $scheme['robot_ids'])){
                        continue;
                    }
                    $content = $scheme['content'];
                    foreach ($content as $ck=>$contentItem){
                        if($contentItem['msg_type'] == MsgTypeConstants::TEXT){
                            $content[$ck]['content'] = TagReplacer::replaceTags($contentItem['content'],[
                                'call_name_nickname' => !empty($contact->call_name) ? $contact->call_name : $contact->nickname,
                            ]);
                        }
                    }
                    $recordData[] = [
                        'uid' => $uid,
                        'main_uid' => $mainUid,
                        'task_id' => $scheme['id'],
                        'robot_id' => $contact->robot_id,
                        'to_id' => $contact->user_id,
                        'trigger_time' => time(),
                        'content' => $content,
                        'msg_total_count' => count($scheme['content']),
                        'type' => SendConfigConstants::SMART_AUTO_PUSH,
                        'status' => SendRecordStatusConstants::WAITING
                    ];
                }
                if(!empty($recordData)){
                    container()->get(Producer::class)->produce(new SendRecordProducers(
                        (new SendRecordProducersDto())
                            ->setMainUid($mainUid)
                            ->setUid($uid)
                            ->setTaskId($scheme['id'])
                            ->setType(SendConfigConstants::SMART_AUTO_PUSH)
                            ->setRecordData($recordData)
                            ->setIsSendNow(true)
                    ));
                }
                Coroutine::sleep(randomFloat(2,4));
            }
        }
        return $filterList;
    }

    /**
     * 获取发送配置
     * @param $robotId
     * @param $uid
     * @return array
     */
    private function getSendConfig($robotId,$uid): array
    {
        $sendConfig = $this->sendConfigService->getConfig(SendConfigConstants::SMART_AUTO_PUSH,$uid,$robotId);
        //获取发送对象间隔
        $sendObjectInterval = mt_rand($sendConfig['send_object_interval_min'], $sendConfig['send_object_interval_max']);
        //休眠时间段开关
        $sleepPeriodSwitch = $sendConfig['sleep_period_switch'];

        //休眠时间段
        list($sleepStartTime,$sleepEndTime) = get_sleep_time($sendConfig['sleep_start_time'],$sendConfig['sleep_end_time']);

        $needToSleep = false;
        if($sleepPeriodSwitch && $sleepStartTime <= time() && time() <= $sleepEndTime){
            $needToSleep = true;
        }

        if($needToSleep){
            $startTime = $sleepEndTime;
        }else{
            $startTime = time();
        }
        return [$sendObjectInterval,$startTime];
    }
}